package com.lagou.client;

import com.lagou.pojo.RpcRequest;
import com.lagou.util.RequestMetrics;
import org.I0Itec.zkclient.ZkClient;

import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class RpcConsumer {

    public static ZkClient zkClient = new ZkClient("127.0.0.1:2181",5000);

    //创建线程池对象
    private static ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

    public static Map<String, RpcClient> clientMap = new HashMap<>();

    //1.创建一个代理对象
    public Object createProxy(final Class<?> serviceClass, final String className,final String methodName){
        //借助JDK动态代理生成代理对象
        return  Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[]{serviceClass}, (proxy, method, args) -> {
            //获取服务器节点并根据节点获取handler
            String address  = RequestMetrics.selector();
            if(clientMap==null){
                return "no server now!please wait";
            }
            if(address==null||!clientMap.containsKey(address)){
                address = (String) clientMap.keySet().toArray()[0];
            }
            NettyClientHandler nettyClientHandler = clientMap.get(address).handler;
            // 设置参数
            RpcRequest req = new RpcRequest();
            String reqId = UUID.randomUUID().toString();
            req.setRequestId(reqId);
            //className必须与服务端中的实现类在ioc容器内的名称完全一致，否则会找不到实现类对象
            req.setClassName(className);
            //使用灵活判断途径时，方法名和方法传参类型列表都必须完全一致
            req.setMethodName(methodName);
            Class<?>[] clazz = {String.class};
            req.setParameterTypes(clazz);
            //实际传参
            args[0] = reqId+","+args[0];
            req.setParameters(args);
            //userClientHandler.setPara(providerName+args[0]);
            nettyClientHandler.setPara(req);

            // 去服务端请求数据
            return executor.submit(nettyClientHandler).get();
        });


    }



    //2.初始化netty客户端
    public void init() throws InterruptedException {
        //bootstrap.connect("127.0.0.1",8990).sync();

        List<String> children = zkClient.getChildren("/provider");
        System.out.println(children);
        connectList(children);

    }


    public void connectList(List<String> children) throws InterruptedException {
        for (String address : children) {
            String[] i_p = address.split(":");
            RpcClient client = new RpcClient(i_p[0],Integer.valueOf(i_p[1]),this);
            client.connect();
            clientMap.put(address, client);
            RequestMetrics.addNode(address);
        }
    }

}
